package com.jason.system.common.shiro;

import com.auth0.jwt.exceptions.TokenExpiredException;
import com.jason.system.common.jwt.JwtToken;
import com.jason.system.common.util.JwtUtil;
import com.jason.system.entity.AdminPermission;
import com.jason.system.entity.AdminRole;
import com.jason.system.entity.User;
import com.jason.system.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthenticatingRealm;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author jie
 * @version 1.0
 * success come from self-discipline
 * @date 2021/3/22 20:39
 */
@Component
public class ShiroRealm extends AuthorizingRealm {

  private static final Logger logger = LoggerFactory.getLogger(Logger.class);

  @Autowired
  private UserService userService;

  /**
   * 自定义实现的JwtToken能支持系统默认的UserPasswordToken
   * @param token
   * @return true or false
   */
  @Override
  public boolean supports(AuthenticationToken token) {
    return token !=null && token instanceof JwtToken;
  }

  /**
   * @MethodName doGetAuthorizationInfo
   * @Description 权限配置类
   * @param principalCollection
   * @return AuthorizationInfo
   */
  @Override
  protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
    logger.info("==>>用户授权中");
    //获取登录用户名
    String name = principalCollection.getPrimaryPrincipal().toString();
    //查询用户名称
    User user = userService.getUserByName(name);
    //添加角色权限
    SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
    //获取用户角色信息
    AdminRole role = user.getRole();
    //添加角色
    simpleAuthorizationInfo.addRole("role:"+role.getRoleName());
    //添加权限
    for (AdminPermission permission : role.getPermissions()){
      simpleAuthorizationInfo.addStringPermission("permission:"+permission.getPermissionName());
    }
    return simpleAuthorizationInfo;
  }

  @Override
  protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
    logger.info("==>>用户身份认证中");
    String name = JwtUtil.getUsernameFromToken(authenticationToken.getPrincipal().toString());
    //遇到了不同用户用同一token去请求接口，而jwtfliter拦截后没有去验证用户信息是否相同
    logger.info("--->>>ShiroRealm::doGetAuthenticationInfo方法中获取token中的" +
            "Credentials信息:[{}]",authenticationToken.getCredentials());
    logger.info("--->>>ShiroRealm::doGetAuthenticationInfo方法中获取token中的" +
            "principal信息:[{}]",authenticationToken.getPrincipal());
    //获取用户信息
    User user = userService.getUserByName(name);
    if(user == null){
      //这里返回后会报出对应异常
      return null;
    }else {
      //这里验证authenticationToken和simpleAuthenticationInfo的信息
      //principle使用用户名，credentials使用token
      //因为这里使用的是jwtToken形式，不是使用用户和密码的验证方式，所有credentials不是使用数据查出的密码。
      return new SimpleAuthenticationInfo(name,authenticationToken.getCredentials(),"ShiroRealm");
    }
  }
}
